package com.qf.qfuser.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.qf.qfcommons.pojo.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.concurrent.atomic.AtomicInteger;

//@RestController
//@RequestMapping("/user")
////类级别的降级操作
//@DefaultProperties(defaultFallback="default_fallback")
public class UserController2 {


    @Autowired
    private RestTemplate restTemplate;

    //利用Hystrix注解，标识这个方法为受保护资源
    @GetMapping("/{id}")
    /*
        保护这个资源的方式：
            ① 超时机制，默认是1s
            ② 内部会新建一个线程池，隔离这个操作
            ③ 当这个方法在一定时间内，访问失败的概率达到某一个阈值时，后续访问直接不发起
     */

    /*
        fallbackMethod: 配置方法级别的降级操作。 （降级：当访问的远程方法出现问题-超时、异常，返回一些友好提示数据）
            要求：降级方法的声明必须和被保护方法的声明一致
                返回值一致
                参数列表一致。 可以在其他参数一致的基础上，额外增加一个异常对象(可选)

        类上配置@DefaultProperties的defaultFallback属性：配置类级别的降级操作
            要求：降级方法的返回值必须和受保护方法的返回值一致。参数列表空参。
                在参数列表空参的基础上，额外增加一个异常对象(可选)

        降级方法优先级：方法级别的优先级高于类级别的
     */
    @HystrixCommand(commandProperties = {
            //配置远程调用超时时间，默认是1s
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3500"),

            //统计10s内，请求次数是否超过2次，而且这2次请求中错误比例是否超过50%。 是--触发熔断，在接下来的10s内，访问这个远程业务时，直接走降级
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "2"),
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"),
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "50"),
    },
            threadPoolProperties = {
            //配置隔离线程池的核心线程数和最大线程数
            @HystrixProperty(name = "coreSize",value = "5")
    }
    )
    public R findOrders(@PathVariable("id") Integer id) throws InterruptedException {

        //通过RestTemplate向Order服务发起请求，获取订单数据
        R r = restTemplate.getForObject("http://QF-ORDER/order/"+id, R.class);
        return r;
    }

    public R findOrders_fallback(Integer id,Throwable t){
        t.printStackTrace();
        return R.error().putMsg("服务器忙，稍后重试。。。");
    }

    public R default_fallback(Throwable t){
        t.printStackTrace();
        return R.error().putMsg("服务器忙，稍后重试,类级别。。。");
    }
}
